/*
 * @Author: hongbin
 * @Date: 2023-06-23 19:36:12
 * @LastEditors: hongbin
 * @LastEditTime: 2023-06-23 21:32:16
 * @Description:
 */
import { FC } from "react";
import * as THREE from "three";
import { ThreeHelper } from "@/ThreeHelper";
import Layout from "@/components/Three/Layout";
import { NoiseShaderMaterial } from "@/ThreeHelper/shader/noise/NoiseMaterial";

interface IProps {}

const destroyEvent = [] as VoidFunction[];

const Index: FC<IProps> = () => {
    return (
        <Layout
            seoTitle={"噪音背景"}
            init={init}
            destroy={() => destroyEvent.forEach((destroy) => destroy())}
        />
    );
};

export default Index;

async function init(helper: ThreeHelper) {
    helper.addStats();
    helper.camera.position.set(0, 0, 10);
    helper.frameByFrame();
    helper.addGUI();
    helper.addAxis();
    helper.useRoomEnvironment();
    helper.setBackground("#7d7866");

    const gui = {
        info: () => {
            console.log(helper.camera.fov);
            console.log(helper.camera.aspect);
        },
        fov: helper.camera.fov,
    };

    helper.gui?.add(gui, "info");

    helper.gui?.add(gui, "fov", 0, 360).onChange((fov) => {
        helper.camera.fov = fov;
        helper.camera.updateProjectionMatrix();
    });

    const noiseBg = new NoiseBg(helper.camera);

    helper.add(noiseBg.plane);

    const box = new THREE.Mesh(
        new THREE.BoxGeometry(3, 3, 3),
        new THREE.MeshStandardMaterial({ color: "#fa5" })
    );
    helper.add(box);
}

class NoiseBg {
    plane: THREE.Mesh<THREE.PlaneGeometry, THREE.ShaderMaterial>;

    constructor(camera: THREE.PerspectiveCamera) {
        const vFOV = (camera.fov * Math.PI) / 180;

        const height = 2 * Math.tan(vFOV / 2) * camera.position.z;

        const width = height * camera.aspect;

        const material = this.noiseMaterial();

        this.plane = new THREE.Mesh(
            new THREE.BoxGeometry(width * 10, height * 10, width * 10, 1, 1),
            material
            // NoiseShaderMaterial
        );
        this.plane.onAfterRender = () => {
            this.plane.material.uniforms.iTime.value += 0.01;
            // this.plane.material.uniforms.vTime.value += 0.01;
        };
    }

    noiseMaterial() {
        const material = new THREE.ShaderMaterial({
            uniforms: {
                iTime: { value: 1 },
            },
            side: THREE.BackSide,
            transparent: true,
            vertexShader: `
            varying vec2 vUv;
            
            void main() {
                vUv = uv;
                vec4 viewPosition =modelViewMatrix * vec4(position, 1.0);
                gl_Position =  projectionMatrix * viewPosition;
                // gl_Position =  vec4(position, 1.0);
            }`,
            fragmentShader: `
            varying vec2 vUv;
            uniform float iTime;

            #define PI 3.141592653589793

            highp float rand( const in vec2 uv ) {

                const highp float a = 12.9898, b = 78.233, c = 43758.5453;
                highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );
            
                return fract( sin( sn ) * c );
            
            }
                    
            void main() {
                vec3 color = vec3(rand(vUv * iTime));
                gl_FragColor = vec4(color, 0.4);
            }`,
        });
        return material;
    }
    // noiseMaterial() {
    //     const material = new THREE.ShaderMaterial({
    //         uniforms: {
    //             iTime: { value: 0 },
    //         },
    //         vertexShader: `
    //         varying vec3 vColor;
    //         uniform float iTime;
    //         #define PI 3.141592653589793

    //         highp float rand( const in vec2 uv ) {

    //             const highp float a = 12.9898, b = 78.233, c = 43758.5453;
    //             highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );

    //             return fract( sin( sn ) * c );

    //         }

    //         void main() {

    //             vec4 viewPosition = modelViewMatrix * vec4(position, 1.0);
    //             gl_Position = projectionMatrix * viewPosition;
    //             vColor = vec3(rand(uv * iTime),0.5,0.8);

    //         }`,
    //         fragmentShader: `
    //         varying vec3 vColor;

    //         void main() {

    //             gl_FragColor = vec4(vColor, 1.0);
    //         }`,
    //     });
    //     return material;
    // }
}
